package com.suncreate.radarscan.web;

import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.server.standard.SpringConfigurator;

import com.suncreate.radarscan.model.RawRadarData;

//websocket连接URL地址和可被调用配置
@ServerEndpoint(value="/getdata/{radarId}",configurator = SpringConfigurator.class)
public class WebSocketController {
	//日志记录        
    private Logger logger = LoggerFactory.getLogger(WebSocketController.class);
    
    //用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    //记录请求每一个雷达下多个终端的连接,key是雷达的ID,value是请求该雷达数据的所有客户端session
    private static Map<String, Set<WebSocketController>> userSocket = new HashMap<>();

    //记录每次客户端连接的session
    private Session session;
    
    //记录每次客户端请求的雷达Id
    private String radarId;
    
    /**
     * 用来标记消息推送是否开始
     * 1.false:程序启动后的状态为没有开始推送数据
     * 2.true:开始推送数据的状态，如果有客户端连接请求就开始推送数据
     */
//    private static boolean isSendMessageStart = false;
    
//    @Autowired
//    private KafkaConsumerDao kafkaConsumerDao;
    
    /**
     * @Description: 有客户端连接时执行此函数，添加客户端请求雷达Id、请求session(<radarId,session>)到userSocket中
     * @param radarId:客户端请求雷达Id
     * @param session:客户端连接session
     * @throws IOException
     */
    @OnOpen
    public void onOpen(@PathParam("radarId") String radarId,Session session){
        try {
			this.session = session;
			this.radarId = radarId;
			
			//当前在线客户端总数加1
			onlineCount++;
			
			/**
			 *根据客户端请求的雷达Id是否被请求过进行操作
			 *如果客户端请求的雷达已经被请求过，则将客户端连接session加入到雷达Id对应的session集合中
			 *否则，在userSocket中创建一个key=radarId，并将客户端session加入到对应的集合中
			 */
			if (userSocket.containsKey(this.radarId)) {
				logger.debug("当前雷达id:{}已有其他客户端访问", this.radarId);
				userSocket.get(this.radarId).add(this); //增加该用户set中的连接实例
			} else {
				logger.debug("当前雷达id:{}第一次被客户端访问", this.radarId);
				Set<WebSocketController> addUserSet = new HashSet<>();
				addUserSet.add(this);
				userSocket.put(this.radarId, addUserSet);
			}
			
			logger.debug("雷达ID为{}的雷达当前被访问的客户端个数是{}", radarId, userSocket.get(this.radarId).size());
			logger.debug("当前被客户端访问的雷达个数为：{},所有客户端个数为：{}", userSocket.size(), onlineCount);
			
			/**
			 * 只有在第一个客户端连接时，才启动数据推送服务，新开一个线程专门负责雷达数据推送
			 */
//			if (!isSendMessageStart) {
//				//sendMessageToClients();
//				logger.debug("=======================");
//				isSendMessageStart = true;
//			} 
		} catch (Exception ex) {
			logger.error("",ex);
		}
    }

    /*
     * 客户端关闭连接时执行，用来删除userSocket中客户端连接记录
     */
    @OnClose
    public void onClose(){
    	try {
			if (null == userSocket) {
				return;
			}
			//删除radarId对应的session连接，如果此radarId对应的所有session都删除了，则删除此radarId的记录
			userSocket.get(this.radarId).remove(this);
			if (userSocket.get(this.radarId).size() == 0) {
				userSocket.remove(this.radarId);
			}
			
			//当前连接客户端个数减1
			onlineCount--;
			
			logger.debug("当前被客户端访问的雷达个数为：{},所有客户端个数为：{}", userSocket.size(), onlineCount);
		} catch (Exception ex) {
			logger.error("",ex);
		}
    }

    /*
     * 接收到客户端消息时执行，由于只是数据推送，故此部分代码没有实现，后期可以根据业务需求进行扩充
     */
    @OnMessage
    public void onMessage(String message, Session session) { 
        logger.debug("收到客户端的请求：请求的URI为{},请求的雷达ID为:{},收到客户端的消息为:{}",session.getRequestURI(),this.radarId,message);
        if(session ==null)  logger.debug("session null");
    }
    

    /*
     * 客户端连接错误时执行,这部分逻辑待测试，到底应不应该在userSocket中删除session?
     */
    @OnError
    public void onError(Session session, Throwable error){
        logger.error("客户端请求发送错误，客户端请求URI为:{},请求的雷达ID为:{}",session.getRequestURI(),this.radarId);
        logger.error("",error);
    }

    /**
     * @Description:向所有请求此radarId的所有客户端推送数据 
     * @param radarId：请求的雷达Id
     * @param message:向客户端推送的数据
     * @return Boolean:消息推送成功返回true,否则为false
     */
//    public Boolean sendMessageByRadarId(String radarId,String message){
//        if (userSocket.containsKey(radarId)) {
//            for (WebSocketController WS : userSocket.get(radarId)) {
//                logger.debug(" 给请求雷达ID为{}的所有客户端发送消息，发送的消息是：{}",radarId,message);
//                try {
//                    WS.session.getBasicRemote().sendText(message);
//                } catch (IOException e) {
//                    e.printStackTrace();
//                    logger.debug(" 给客户端发送消息失败,此客户端SessionID为:{},客户端请求URI为:{}",radarId,WS.session.getRequestURI());
//                }
//            }
//            return true;
//        }
//        return false;
//    }
//    
    /**
     * @Description:根据userSocket中记录的客户端session，向当前连接的所有客户端推送数据 
     */
    
    
//    public void sendMessageToClients(){
//        try
//        {
//            Thread t=new Thread(){
//                @Override
//                public void run() {
//                   while (true) {
//                        ConsumerRecords<String, String> records = kafkaConsumerDao.readKafka();
//                        //推送数据
//                        for (ConsumerRecord<String, String> record : records) {
//                            RawRadarData rawRadarData = (RawRadarData)JsonUtil.getDTO(record.value(), RawRadarData.class);
//                            sendMessageByRadarId(rawRadarData.getRadarId(),record.value());
//                        }
//                    }
//                	/*
//                	while(true) {
//                		for(int i=1;i<=10;i++){
//                    		RawRadarData radarData = new RawRadarData();
//                    		//"XSpeed":36.0,"YSpeed":-2.16,"radarId":"SC001","fAZM":0.0,"time":"2017-08-18 11:53:34"}
//                    		radarData.setiTargetStatus(1);
//                    		radarData.setiTargetType(2);
//                    		radarData.setiTargetNum(i+1);
//                    		radarData.setiTargetSum(10);
//                    		radarData.setXDistance(2);
//                    		radarData.setYDistance((float)(Math.random()*20 + i*10));
//                    		radarData.setXSpeed(36.0f);
//                    		radarData.setYSpeed(-2.16f);
//                    		radarData.setRadarId("SC001");
//                    		radarData.setfAZM(0.0f);
//                    		radarData.setTime("2017-08-18 11:53:34");
//                    		try {
//    							String radarDataString = JsonUtil.getJSONString(radarData);
//    							sendMessageByRadarId("SC001",radarDataString);
//    							try {
//    								Thread.sleep(50);
//    							} catch (InterruptedException e) {
//    								// TODO Auto-generated catch block
//    								e.printStackTrace();
//    							}
//    						} catch (Exception e1) {
//    							// TODO Auto-generated catch block
//    							e1.printStackTrace();
//    						}
//                    		
//                    		
//                    		
//                    	}
//                	}*/
//                	
//                }
//            };
//            t.start();
//        }
//        catch(Exception ex)
//        {
//            System.out.println(ex.toString());
//        }
//    }
    
}
